package com.tanhua.api.impl.mongo;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import com.tanhua.api.mongo.SoulTestApi;
import com.tanhua.domain.mongo.*;
import com.tanhua.domain.vo.SoulVo;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.util.*;

@Service
public class SoulTestApiImpl implements SoulTestApi {
    @Autowired
    private IdService idService;
    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public List<SoulVo> soulQuestion(Long userId) {
        UserLevel userLevel = mongoTemplate.findOne(new Query(Criteria.where("userId").is(userId)), UserLevel.class);
        if (BeanUtil.isEmpty(userLevel)) {
            userLevel = new UserLevel();
            userLevel.setUserId(userId);
            userLevel.setLevel(1);
            mongoTemplate.save(userLevel);
        }
        List<Soul> list1 = mongoTemplate.find(new Query(Criteria.where("level").is("初级")), Soul.class);
        List<Soul> list2 = mongoTemplate.find(new Query(Criteria.where("level").is("中级")), Soul.class);
        List<Soul> list3 = mongoTemplate.find(new Query(Criteria.where("level").is("高级")), Soul.class);

        List<Soul> souls = new ArrayList<>();
        souls.add(list1.get(RandomUtil.randomInt(list1.size())));
        souls.add(list2.get(RandomUtil.randomInt(list2.size())));
        souls.add(list3.get(RandomUtil.randomInt(list3.size())));
        List<SoulVo> vos = new ArrayList<>();
        for (Soul soul : souls) {
            SoulVo vo = new SoulVo();
            BeanUtil.copyProperties(soul, vo);
            vo.setId(soul.getSoulId().toString());
            List<SoulQuestion> question = getQuestionList(soul);
            vo.setQuestions(question);
            if (vo.getLevelNum() > userLevel.getLevel()) {
                vo.setIsLock(1);
            }
            vos.add(vo);
        }
        return vos;
    }

    @Override
    public String testSoul(List<Answer> answers, Long userId) {
        List<QuestionOption> options = new ArrayList<>();
        List<Dimension> dimensions = Dimension.getDimensions();
        Map<String, Integer> map = new HashMap<>();
        map.put("外向", 0);
        map.put("判断", 0);
        map.put("抽象", 0);
        map.put("理性", 0);
        for (int i = 0; i < answers.size(); i++) {
            String optionId = answers.get(i).getOptionId();
            String questionId = answers.get(i).getQuestionId();
            QuestionList questionList = mongoTemplate.findOne(new Query(Criteria.where("questionId").is(Long.valueOf(questionId))), QuestionList.class);
            QuestionOption option = questionList.getOptions().get(Integer.parseInt(optionId) - 1);
            map = getOptionMap(option, map);
        }
        Integer outgoing = map.get("外向");
        Integer judge = map.get("判断");
        Integer abstr = map.get("抽象");
        Integer rational = map.get("理性");

        for (Dimension dimension : dimensions) {
            dimension.setValue(map.get(dimension.getKey()) + "%");
        }
        Report report = new Report();
        Integer remarkId = report.getRemarkId(outgoing, judge, abstr, rational);
        ReportRemark reportRemark = mongoTemplate.findOne(new Query(Criteria.where("remarkId").is(remarkId)), ReportRemark.class);
        report.setCreated(new Date().getTime());
        report.setDimensions(dimensions);
        Long reportId = idService.getNextId("soul_test_report");
        report.setReportId(reportId);
        List<String> conclusion = reportRemark.getConclusion();

        report.setConclusion(conclusion.get(RandomUtil.randomInt(conclusion.size())));
        report.setCover(reportRemark.getCover());
        List<UserRemark> remarks = mongoTemplate.find(new Query(Criteria.where("remarkId").is(remarkId)), UserRemark.class);
        List<Long> ids = new ArrayList<>();
        for (UserRemark remark : remarks) {
            ids.add(remark.getUserId());
        }
        ids.remove(userId);
        report.setSimilarYouIds(ids);
        mongoTemplate.save(report);
        UserLevel userLevel = mongoTemplate.findOne(new Query(Criteria.where("userId").is(userId)), UserLevel.class);
        if (userLevel.getLevel() < 3) {
            userLevel.setLevel(userLevel.getLevel() + 1);
        }
        UserRemark userRemark = mongoTemplate.findOne(new Query(Criteria.where("userId").is(userId)), UserRemark.class);
        if (BeanUtil.isEmpty(userRemark)) {
            userRemark = new UserRemark();
        }

        userRemark.setRemarkId(remarkId);
        userRemark.setUserId(userId);
        mongoTemplate.save(userRemark);
        mongoTemplate.save(userLevel);
        return reportId.toString();
    }

    @Override
    public Report getReport(String pid) {
        Report report = mongoTemplate.findOne(new Query(Criteria.where("reportId").is(Long.valueOf(pid))), Report.class);

        return report;
    }

    private List<SoulQuestion> getQuestionList(Soul soul) {
        List<String> questionIds = soul.getQuestionIds();
        List<SoulQuestion> lists = new ArrayList<>();
        for (String id : questionIds) {
            QuestionList questionList = mongoTemplate.findOne(new Query(Criteria.where("questionId").is(Long.valueOf(id))), QuestionList.class);
            SoulQuestion soulQuestion = new SoulQuestion(questionList);
            lists.add(soulQuestion);
        }
        return lists;
    }

    private Map<String, Integer> getOptionMap(QuestionOption option, Map<String, Integer> map) {
        map.put(option.getAbstr(), option.getAbstrValue() + map.get(option.getAbstr()));
        map.put(option.getJudge(), option.getJudgeValue() + map.get(option.getJudge()));
        map.put(option.getOutgoing(), option.getOutgoingValue() + map.get(option.getOutgoing()));
        map.put(option.getRational(), option.getRationalValue() + map.get(option.getRational()));
        return map;
    }
}
